package org.msfj.admin.data.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import org.msfj.admin.data.service.HolidayService;
import org.msfj.admin.model.Holiday;
import org.msfj.admin.vo.HolidayVo;
import org.msfj.admin.data.service.HolidayService;
import org.msfj.admin.model.Holiday;
import org.msfj.admin.vo.HolidayVo;
import org.msfj.admin.data.mapper.HolidayMapper;
import org.msfj.admin.data.service.HolidayService;
import org.msfj.admin.model.Holiday;
import org.msfj.admin.vo.HolidayVo;
import org.msfj.common.annotation.Constants;
import org.msfj.common.base.BaseServiceImpl;
import org.msfj.common.enums.Enable;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import cn.hutool.core.collection.CollectionUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Description: 系统节假日service实现类
 * @Author: like
 * @Email: like@deyatong.com
 * @Date: 2017-08-10 17:30:20
 * @Version: 1.0
 * @Created in idea by autoCode
 */

@Service
@CacheConfig(cacheNames = Constants.CACHE_NAMESPACE + "holiday")
public class HolidayServiceImpl extends BaseServiceImpl<Holiday> implements HolidayService {
    @Autowired
    private HolidayMapper holidayMapper;

    /**
     * 根据条件分页查询系统节假日列表
     *
     * @param holidayVo
     * @param page      当前第几页
     * @param rows      每页多少条记录
     * @return PageInfo<Holiday>
     */
    @Override
    //@Cacheable
    public PageInfo<HolidayVo> getByHoliday(HolidayVo holidayVo, int page, int rows) {
        Example example = new Example(Holiday.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("enable", Enable.ENABLE.getCode());
        PageHelper.startPage(page, rows);
        List<Holiday> holidayList = super.getByExample(example);
        PageInfo holidayVoPageInfo = new PageInfo(holidayList);
        holidayVoPageInfo.setList(setOtherProperties(holidayList));
        return holidayVoPageInfo;
    }

    /**
     * 根据条件查询所有系统节假日对象列表
     *
     * @param holidayVo
     * @return List<Holiday>
     */
    @Override
    //@Cacheable
    public List<HolidayVo> getAllHoliday(HolidayVo holidayVo) {
        Example example = new Example(Holiday.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("enable", Enable.ENABLE.getCode());
        if (ObjectUtil.isNotNull(holidayVo)) {
            if (StrUtil.isNotBlank(holidayVo.getYear())) {
                criteria.andEqualTo("year", holidayVo.getYear());
            }
        }
        List<HolidayVo> holidayVoList = setOtherProperties(super.getByExample(example));
        return holidayVoList;
    }

    /**
     * 设置vo的其他属性属性
     *
     * @param holiday
     * @return DepartmentVo
     */
    @Override
    //@Cacheable
    public HolidayVo setOtherProperties(Holiday holiday) {
        HolidayVo holidayVo = new HolidayVo();
        BeanUtils.copyProperties(holiday, holidayVo);
        return holidayVo;
    }

    /**
     * 设置vo的其他属性属性
     *
     * @param holidays
     * @return List<HolidayVo>
     */
    @Override
    //@Cacheable
    public List<HolidayVo> setOtherProperties(List<Holiday> holidays) {
        List<HolidayVo> holidayVos = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(holidays)) {
            for (Holiday holiday : holidays) {
                HolidayVo holidayVo = new HolidayVo();
                BeanUtils.copyProperties(holiday, holidayVo);
                holidayVos.add(holidayVo);
            }
        }
        return holidayVos;
    }

    /**
     * 保存节假日
     *
     * @param year
     * @param holidayList
     * @param userId
     */
    @Override
    @Transactional
    public void saveHoliday(String year, List<String> holidayList, String userId) {
        List<Holiday> holidays = CollectionUtil.newArrayList();
        Example example = new Example(Holiday.class);
        example.createCriteria().andEqualTo("year", year);
        holidayMapper.deleteByExample(example);
        if (CollectionUtil.isNotEmpty(holidayList)) {
            for (String string : holidayList) {
                Holiday holiday = new Holiday();
                holiday.setYear(year);
                holiday.setDate(string);
                holiday.setCreateBy(userId);
                holiday.setUpdateBy(userId);
                holidays.add(holiday);
            }
            super.saveList(holidays);
        }
    }

    @Override
    public Date workDayAfter(Date date, Integer day) {
        Integer lastHoliday = 0;
        Date after = DateUtil.offsetDay(date, day);
        int hasHolidays = hasHolidays(date, after);
        for (int i = hasHolidays - lastHoliday; i > 0; ) {
            lastHoliday = hasHolidays;
            after = DateUtil.offsetDay(date, day + hasHolidays);
            hasHolidays = hasHolidays(date, after);
            i = hasHolidays - lastHoliday;
        }
        return after;
    }

    @Override
    public Date workHourAfter(Date date, Integer hour) {
        Integer lastHoliday = 0;
        Date after = DateUtil.offsetHour(date, hour);
        int hasHolidays = hasHolidays(date, after);
        for (int i = hasHolidays - lastHoliday; i > 0; ) {
            lastHoliday = hasHolidays;
            after = DateUtil.offsetHour(date, hour + (hasHolidays * 24));
            hasHolidays = hasHolidays(date, after);
            i = hasHolidays - lastHoliday;
        }
        return after;
    }

    @Override
    public boolean isHoliday(Date today) {
        Example example = new Example(Holiday.class);
        example.createCriteria().andEqualTo("date", DateUtil.format(today, "yyyy-MM-dd"))
                .andEqualTo("enable", 1);
        int i = this.holidayMapper.selectCountByExample(example);
        return i > 0;
    }


    private int hasHolidays(Date startDate, Date endDate) {
        int totle = 0;
        String startYear = DateUtil.format(startDate, "yyyy");
        String endYear = DateUtil.format(endDate, "yyyy");
        List<HolidayVo> all = new ArrayList<>();
        if (startYear.equals(endYear)) {
            all = findHolidayByYear(Integer.valueOf(startYear));
        } else {
            all.addAll(findHolidayByYear(Integer.valueOf(startYear)));
            all.addAll(findHolidayByYear(Integer.valueOf(endYear)));
        }
        double twoDate = DateUtil.betweenDay(startDate, endDate, false);
        for (Holiday holiday : all) {
            String result = holiday.getDate();
            for (int i = 0; i <= (int) twoDate; i++) {
                String start = DateUtil.formatDate(DateUtil.offsetDay(startDate, i));
                if (result.equals(start)) {
                    totle++;
                }
            }
        }
        return totle;
    }

    private List<HolidayVo> findHolidayByYear(Integer year) {

        HolidayVo vo = new HolidayVo();
        vo.setYear(year.toString());
        return this.getAllHoliday(vo);
    }
}
